<!DOCTYPE HTML>
<html>
<head>
	<title>鼠标拖动和缩放demo</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<meta name="viewport"
		content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=2.0, user-scalable=yes">
	
	<script type="text/javascript" src="js/jquery-3.1.1.js"></script>
	
	<style type="text/css">
		html, body {
			width: 100%;
			height: 100%;
			padding: 5px;
			background-color: #fff;
			color: #111;
			overflow: hidden;
		}
	
		canvas {
			background-color: #ccc;
		}
	</style>
	
	<script type="text/javascript">
	  		
	</script>
</head>
<body>
	<canvas id="can" width="800" height="500"></canvas>
	<div>>
		<button id="btn_in">放大</button>
		<button id="btn_normal">还原</button>
		<button id="btn_out">缩小</button>
	</div>
	<div>1 不管是否点中红球，都能拖动； 2 包含缩放和拖动</div>
	<div id="posdiv"></div>
	
	<script type="text/javascript">
		var can = document.getElementById("can");
		var ctx = can.getContext("2d");
		var isDown = false;
		var dx = 0, 
			dy = 0; // 鼠标按下位置的坐标
		var offx = 0, offy = 0; // 拖动的距离，x,y
		var centerx = 50,
			centery = 50; // 圆心坐标
		
		var cx = 0, cy = 0; // 画布中心点坐标
		
		// 原始比率(scaler = 1)时，拖动产生的偏移量
		var _x  = 0, _y  = 0; // 这个变量用来计算缩放后的偏移量误差

		var scaler = 1; // 缩放比率
		
		/**
		 * 创建圆滑块:  圆心坐标  x,y
		 */
		function createBlock(fished) {
			/**
			 * 画布中心点 + （中心点与圆心间距*缩放系数）  + 偏移量 
			 */
			var nx = cx + (centerx-cx)*scaler + offx;
			var ny = cy + (centery-cy)*scaler + offy;
			
			ctx.clearRect(0, 0, can.width, can.height);
			ctx.beginPath();
			ctx.save();
			// ctx.translate(cx, cy);
			ctx.fillStyle = "red";
			
			console.log("圆心坐标="+centerx+","+centery+"画布中心点="+cx+", "+cy);
			ctx.arc(nx, ny, 30*scaler, 0, Math.PI * 2);
			ctx.fill();
			ctx.restore();
		}
		
		//鼠标按下，将鼠标按下坐标保存在x,y中  
		can.onmousedown = function(ev) {
			var e = ev || window.event;
			dx = e.clientX;
			dy = e.clientY;
			isDown = true;
			can.onmousemove = function(ev) {
				$("#posdiv").html("鼠标坐标，x="+ev.clientX+", y="+ev.clientY);
				if (isDown) {
					var e = ev || window.event;
					var mx = e.clientX;
					var my = e.clientY;
	
					offx = mx - dx;
					offy = my - dy;
					
					createBlock();
				}
			};
			//鼠标移开事件  
			can.onmouseup = function(ev) {
				isDown = false;
				var e = ev || window.event;
				createBlock(true);
				
				// 重置
				centerx += (e.clientX - dx)/scaler;
				centery += (e.clientY - dy)/scaler;
				
				offx = 0;
				offy = 0;
				can.onmousemove = null;
				can.onmouseup = null;
			};
			
			var bb = (ctx.canvas).getBoundingClientRect();
		};
	
		var mouseHandler = function(ev) {
			if (ev.type == "mousewheel") {
				var e = (ev || window.event).originalEvent;
				var deltaY = e.wheelDelta;
				
				if(deltaY == 120) {
					$("#btn_in").trigger("click");
				} else if(deltaY == -120) {
					$("#btn_out").trigger("click");
				}
			}
		};
		
		$(can).off().on({
			mousewheel : mouseHandler,
		});
		
		$(function(){
			cx = $("canvas")[0].width / 2;
			cy = $("canvas")[0].height / 2;
			createBlock();
			$("#btn_in").off().on({
				"click": function() {
					scaler += 0.5;
					createBlock();
					
				}
			});
			
			$("#btn_normal").off().on({
				"click": function() {
					scaler = 1;
					_x  = 0, _y  = 0;
					createBlock();
				}
			});
			
			$("#btn_out").off().on({
				"click": function() {
					if (scaler <=1 ){
						alert("alreay smallest, cannot zoom out!");
						return;
					}
					
					scaler -= 0.5;
					createBlock();
				}
			});
		})
	</script>

</body>
</html>